package com.dbpediamobile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

/*
 * Autor: Camilo Verdugo
 * Clase principal de Mapa. Inicia el mapa dividiendo el inicio a partir de busquedas o de un ingreso sin busqueda.
 * Cuando se ingresa la busqueda, se agrega un combobox con los resultados de busqueda y permite la seleccion de ellos.
 * Para los resultados sin busqueda no muestra el combobox y oculta la opcion de menu de ver articulo.
 */
public class Mapa extends MapActivity {
		private Spinner combobox;					//Menu de opciones, el cual despliega los resultados de las busquedas
		private ArrayList <MapaResult> resultados;  //Lista de resultados formateados, cada item tiene url, nombre y coordenadas
		private ArrayAdapter<String> adapter;
		public  String urlActual;					//Registra en la clase DbpediaMobile, el ultimo item seleccionado de la busqueda en mapa
		private static DBPediaMobile dbp;			//Usado para acceder a variables globales.
		public  static String input;
		private MapController mc;
		private Button saveBook;
		private EditText inpuBook;
		private MapaBD mbd;
		public  Context cont;
		private GeoPoint p1;
		private TextView from;
		private TextView to;
		private String estimacion;
		private TextView tvestimacion;
		private ProgressDialog progressD=null;
		private EditText Country0;
		private EditText Country1 ;
		private EditText City0 ;
		private EditText City1 ;
		private EditText Street0 ;
		private EditText Street1 ;
		private Button find;
		private Button cancel;
		private Button cancelBook;
		
	    @Override
	    public void onCreate(Bundle savedInstanceState) {	    	
	    	super.onCreate(savedInstanceState);  
			setContentView(R.layout.mapa);   
	    	cont = this;
	    	progressD = ProgressDialog.show(Mapa.this, "Please wait...", "Loading...", true);	    	
	        new Thread(){public void run() {
	            	try{
	            		sleep(100);
	            		handler.sendEmptyMessage(0);
	            	}catch (Exception e){ }
	            	progressD.dismiss();
		        }
	        }.start();
	       
	    }
	    
	    
	    Handler handler = new Handler(){
			public void handleMessage(Message msg) {
		    	MapView mapView = (MapView) findViewById(R.id.mapview);
	        	mapView.setLongClickable(true);        
	            mapView.setBuiltInZoomControls(true);
	            mapView.setClickable(true);
	            mapView.setOnTouchListener(eventoMapa);
	            mc = mapView.getController();
	            mbd = new MapaBD(cont);
	            dbp = new DBPediaMobile();
	            if(dbp.bip==null){
	            	if(dbp.txtInput.getText().length()>0)
	                {	
	                	try {
	                		MapaConexion c = new MapaConexion();
	    	    			resultados = new ArrayList<MapaResult>();
	    	    			mapView.setSatellite(true); 
	    	    			
	    	    			String query = "+select+distinct+%3Fs1+as+%3Fc1+%3Flat1+as+%3Fc2+%3Flng1+as+%3Fc3++where+{+%3Fs1+%3Fs1textp+%3Fo1+.+%3Fo1+bif:contains++'\""+dbp.txtInput.getText().toString().replace(" ","+")+"\"'++.+%3Fs1+geo:lat+%3Flat1+;+geo:long+%3Flng1+.+}+limit+20++offset+0+";
	    	    			c.query = query;
	    		        	resultados = c.buscar();
	    		        	String[] items =  new String[resultados.size()];
	    		        	
	    		        	for(int i=0;i<resultados.size();i++){
	    		        		items[i] = new String(resultados.get(i).nombre);
	    		        	}
	    		        	if(resultados.size()>1){
	    		        		combobox = new Spinner(cont);
		    	    			mapView.addView(combobox, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
		    	    			adapter = new ArrayAdapter<String>(cont,android.R.layout.simple_spinner_item,items);
	   	    			      	//Small items simple_spinner_item
	   	    			        adapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
	   	    			        combobox.setAdapter(adapter);
	   	    			        combobox.setOnItemSelectedListener(seleccionFiltro);
	    		        	}else{
	    		        		Toast.makeText(getBaseContext(),"Not found", Toast.LENGTH_SHORT).show();				        
	    			        }	    					
	    				} catch (IOException e) {
	    				}	
	                }else{
	                	LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
	        			Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
	        			if (location != null) {
	        				double lat = location.getLatitude();
	        				double lng = location.getLongitude();
	        				p1 = new GeoPoint((int) lat * 1000000, (int) lng * 1000000);
	        				mc.animateTo(p1);
	        				int lati = (int) (location.getLatitude());
	        				int lngi = (int) (location.getLongitude());
	        				p1 = new GeoPoint(lati, lngi);					
		            		mc.animateTo(p1);
		            		mc.setZoom(17);
		            		Toast.makeText(getBaseContext(),"Coordinates by emulator", Toast.LENGTH_SHORT).show();
	        			}else{
	        				p1 = new GeoPoint(-35001052, -71234171);					
		            		mc.animateTo(p1);
		            		mc.setZoom(17);
	        			}
	    		    }
	            }else{
	            	posicionarDesdeBookmarks(dbp.bip);
	            }	
		   }
			
		};
	    
		public void posicionarDesdeBookmarks(BookmarksItemMap bim){
			Toast.makeText(getBaseContext(),bim.imprimir(), Toast.LENGTH_SHORT).show();
			GeoPoint p = new GeoPoint(Integer.parseInt(bim.lat),Integer.parseInt(bim.lon));
	    	mc.animateTo(p);
		    mc.setZoom(17);
	    }
	    
	    private OnItemSelectedListener seleccionFiltro = new OnItemSelectedListener() {
	    	public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
				dbp.urlMap = resultados.get(parent.getSelectedItemPosition()).url;
				MapView mapView = (MapView) findViewById(R.id.mapview);
				MapController mc = mapView.getController();				
				Double latitude  = Double.parseDouble(resultados.get(parent.getSelectedItemPosition()).lat)*1E6;
				Double longitude = Double.parseDouble(resultados.get(parent.getSelectedItemPosition()).lon)*1E6;
				GeoPoint p = new GeoPoint(latitude.intValue(),longitude.intValue());	
	            mc.animateTo(p);
	            mc.setZoom(16);
			}
			public void onNothingSelected(AdapterView<?> arg0) {}
	    };
	    
	    
	    @Override
	    public boolean onCreateOptionsMenu(Menu menu) {
	    	MenuInflater inflater = getMenuInflater();
	        inflater.inflate(R.menu.mapa_menu, menu);
	       
	        if(dbp.txtInput.length()==0){
	        	menu.removeItem(R.id.ShowArticle);
	        }
	        return true;
	    }

	    /*
	     * Gestion los eventos de la opcion menu, para cada uno de ellos, haciendo los distintos llamados.
	     *  
	    */
	    public boolean onOptionsItemSelected(MenuItem item) {
	    	MapView mapView = (MapView) findViewById(R.id.mapview);
	    	Intent intent;
	    	LinearLayout l = (LinearLayout) findViewById(R.id.bookmarkControlMapa);
	    	LinearLayout l1 = (LinearLayout) findViewById(R.id.bookmarkControlMapa1);
	    	LinearLayout l0 = (LinearLayout) findViewById(R.id.bookmarkControlMapa0);
	    	LinearLayout l4 = (LinearLayout) findViewById(R.id.bookmarkControlMapa4);
	    	LinearLayout l2 = (LinearLayout) findViewById(R.id.bookmarkControlMapa2);
	    	LinearLayout l3 = (LinearLayout) findViewById(R.id.bookmarkControlMapa3);
	    	l.removeView(tvestimacion);
	    	switch (item.getItemId())
	    	{
		        case R.id.CurrentPosition:		
		        	LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        			Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        			if (location != null) {
        				double lat = location.getLatitude();
        				double lng = location.getLongitude();
        				p1 = new GeoPoint((int) lat * 1000000, (int) lng * 1000000);
        				mc.animateTo(p1);
        				int lati = (int) (location.getLatitude());
        				int lngi = (int) (location.getLongitude());
        				p1 = new GeoPoint(lati, lngi);					
	            		mc.animateTo(p1);
	            		mc.setZoom(17);
	            		Toast.makeText(getBaseContext(),"Coordinates by emulator", Toast.LENGTH_SHORT).show();
        			}else{
        				MapController mc = mapView.getController();
    					GeoPoint p = new GeoPoint(-35001052, -71234171);					
    		            mc.animateTo(p);
    		            mc.setZoom(17); 
        			}
		        		
		            break;
		        case R.id.ShowCoord:	
		        	Toast.makeText(getBaseContext(),mapView.getMapCenter().toString(), Toast.LENGTH_SHORT).show();				        
		        	break;
		        case R.id.StreetView:	
		        	 mapView.setStreetView(true);	
		        	 mapView.setSatellite(false);  		        	 
		            break;
		        case R.id.SatelliteView:	 
		        	mapView.setSatellite(true); 
		            break;		
		        case R.id.ShowArticle:	 
		        	if(dbp.txtInput.getText().length()>=0 && dbp.urlMap!=null){
		        		this.input= dbp.urlMap;
		        		intent = new Intent(Mapa.this, ArticuloActivity.class);
			            startActivity(intent); 
		        	}
		        	else{
		        		Toast.makeText(getBaseContext(),"First you must have done a search", Toast.LENGTH_LONG).show();
		        	}
		            break;
		        case R.id.Bookmarks:		        	
		        	intent = new Intent(Mapa.this, Bookmarks.class);
			        startActivity(intent); 
		        	break;	
		        case R.id.goBackMapa:		        	
		        	intent = new Intent(Mapa.this, DBPediaMobile.class);
			        startActivity(intent); 
		        	break;	 	
		       
		        case R.id.AddToBookmarks:		        	
		        	inpuBook = new EditText(this);	
		        	inpuBook.setWidth(100);
		        	inpuBook.setHint("Name");
		        	saveBook = new Button(this);
		        	saveBook.setWidth(100);
		        	saveBook.setText("Save");
		        	saveBook.setOnClickListener(saveButton);
		        	cancelBook = new Button(this);
		        	cancelBook.setWidth(100);
		        	cancelBook.setText("Cancel");
		        	cancelBook.setOnClickListener(cancelBookLis);
		        	l.addView(inpuBook);
		        	l.addView(saveBook);
		        	l.addView(cancelBook);
		        	break;
		        case R.id.Tracker:
		        	from		= new TextView(this);
		        	to			= new TextView(this);
		            Country0 	= new EditText(this);
			      	Country1 	= new EditText(this);
			      	City0 		= new EditText(this);
			      	City1 		= new EditText(this);
			      	Street0 	= new EditText(this);
			      	Street1 	= new EditText(this);
		      	  	find 		= new Button(this);
		      	  	cancel 		= new Button(this);
		      	  	find.setOnClickListener(findLocationButton);
		      	  	cancel.setOnClickListener(cancelLocationButton);
		      	  	from.setText("From:");
		      	  	cancel.setText("Cancel");
		      	  	cancel.setWidth(120);
		      	  	to.setText("To:");
			      	find.setText("Find");
			      	find.setWidth(120);
			      	Country0.setWidth(100);
			      	Country0.setHint("Country");
			      	Country1.setWidth(100);
			      	Country1.setHint("Country");
			      	City0.setWidth(100);
			      	City0.setHint("City");
			      	City1.setWidth(100);
			      	City1.setHint("City");
			      	Street0.setWidth(100);
			      	Street0.setHint("Street");
			      	Street1.setWidth(100);
			      	Street1.setHint("Street");
			      	l0.addView(from);
			      	l1.addView(Country0);
		        	l1.addView(City0);
		        	l1.addView(Street0);
		        	l2.addView(Country1);
		        	l2.addView(City1);
		        	l2.addView(Street1);
		        	l3.addView(find);
		        	l3.addView(cancel);
		        	l4.addView(to);
		        	break;
		        case R.id.SaveImage:
					try {
						saveAsImage(mapView);
					} catch (IOException e) {
						e.printStackTrace();
					}
				break;	
		    } 
	        return false;
	    }
	    
	    private void saveAsImage(View view) throws IOException{
	    	Bitmap image = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
	    	view.draw(new Canvas(image));
            String path1 = "/data/data/com.dbpediamobile/files";
            OutputStream fOut = null;
            File file1 = new File(path1, "FitnessGirl_"+System.currentTimeMillis()+".PNG");
            fOut = new FileOutputStream(file1);

            image.compress(Bitmap.CompressFormat.PNG, 100, fOut );
            fOut.flush();
            fOut.close();
            MediaStore.Images.Media.insertImage(getContentResolver(),file1.getAbsolutePath(),file1.getName(),file1.getName());
            Toast.makeText(getBaseContext(),"Image was saved", Toast.LENGTH_SHORT).show();    
	    }
	    
	    private OnClickListener cancelBookLis = new OnClickListener(){
			public void onClick(View arg0) {
				LinearLayout l = (LinearLayout) findViewById(R.id.bookmarkControlMapa);
	        	l.removeView(inpuBook);
	        	l.removeView(cancelBook);
	        	l.removeView(saveBook);
			}
	    };
	    
	    
	    private OnClickListener cancelLocationButton = new OnClickListener(){
			public void onClick(View arg0) {
				LinearLayout l = (LinearLayout) findViewById(R.id.bookmarkControlMapa);
				LinearLayout l1 = (LinearLayout) findViewById(R.id.bookmarkControlMapa1);
				LinearLayout l2 = (LinearLayout) findViewById(R.id.bookmarkControlMapa2);
		    	LinearLayout l3 = (LinearLayout) findViewById(R.id.bookmarkControlMapa3);
		    	LinearLayout l0 = (LinearLayout) findViewById(R.id.bookmarkControlMapa0);
		    	LinearLayout l4 = (LinearLayout) findViewById(R.id.bookmarkControlMapa4);
		    	l0.removeView(from);
		        l1.removeView(Country0);
		        l1.removeView(City0);
		        l1.removeView(Street0);
		        l2.removeView(Country1);
		        l2.removeView(City1);
		        l2.removeView(Street1);
		        l3.removeView(cancel);
		        l3.removeView(find);
		        l4.removeView(to);
			}
	    };
			
	    
	    private OnClickListener findLocationButton = new OnClickListener(){
			public void onClick(View arg0) {
				String origen = "";
				String destino ="";
				
				if(!Country0.getText().toString().equals("")){
					origen = Country0.getText().toString();
				}
				if(!City0.getText().toString().equals("")){
					origen+= ","+City0.getText().toString();
				}
				
				if(!Street0.getText().toString().equals("")){
					origen+= ","+Street0.getText().toString();
				}
				
				
				if(!Country1.getText().toString().equals("")){
					destino = Country1.getText().toString();
				}
				if(!City1.getText().toString().equals("")){
					destino+= ","+City1.getText().toString();
				}
				
				if(!Street1.getText().toString().equals("")){
					destino+= ","+Street1.getText().toString();
				}
				
				MapView mapView  = (MapView) findViewById(R.id.mapview);
				LinearLayout l = (LinearLayout) findViewById(R.id.bookmarkControlMapa);
				LinearLayout l1 = (LinearLayout) findViewById(R.id.bookmarkControlMapa1);
				LinearLayout l2 = (LinearLayout) findViewById(R.id.bookmarkControlMapa2);
		    	LinearLayout l3 = (LinearLayout) findViewById(R.id.bookmarkControlMapa3);
		    	LinearLayout l0 = (LinearLayout) findViewById(R.id.bookmarkControlMapa0);
		    	LinearLayout l4 = (LinearLayout) findViewById(R.id.bookmarkControlMapa4);
		    	
		    	String pairs[]  = getDirectionData(origen.toString(),destino.toString());
		    	if(pairs!=null){
	    			String[] lngLat = pairs[0].split(",");
	    			if(lngLat.length>1){
	    				mapView.getOverlays().clear();
	    				GeoPoint startGP = new GeoPoint((int) (Double.parseDouble(lngLat[1]) * 1E6), (int) (Double.parseDouble(lngLat[0]) * 1E6));
	    				mc = mapView.getController();
		  	            GeoPoint geoPoint = null;
		  	            geoPoint = startGP;
		  	            mc.setCenter(geoPoint);
		  	            
		  	            mc.setZoom(15);
		  	            mapView.getOverlays().add(new MapaGetDirecction(startGP, startGP));
		  	          
		  	            GeoPoint gp1;
		  	            GeoPoint gp2 = startGP;

		  	            for (int i = 1; i < pairs.length; i++) {
		  	                lngLat = pairs[i].split(",");
		  	                gp1 = gp2;
		  	                gp2 = new GeoPoint((int) (Double.parseDouble(lngLat[1]) * 1E6),(int) (Double.parseDouble(lngLat[0]) * 1E6));
		  	                mapView.getOverlays().add(new MapaGetDirecction(gp1, gp2));
		  	            }

		  	            mapView.getOverlays().add(new MapaGetDirecction(gp2, gp2));
		  	            mapView.getController().animateTo(startGP);
		  	            mapView.setBuiltInZoomControls(true);
		  	            mapView.displayZoomControls(true);
		  				
		  	            tvestimacion = new TextView(cont);
		  	            tvestimacion.setText(estimacion);
		  	            l.addView(tvestimacion);
	    			}else{
	    				Toast.makeText(getBaseContext(),"Not found", Toast.LENGTH_SHORT).show(); 
	    			}
	            }else{
	            	 Toast.makeText(getBaseContext(),"Not found", Toast.LENGTH_SHORT).show();    
	            }
	                      
	            l0.removeView(from);
	            l1.removeView(Country0);
	        	l1.removeView(City0);
	        	l1.removeView(Street0);
	        	l2.removeView(Country1);
	        	l2.removeView(City1);
	        	l2.removeView(Street1);
	        	l3.removeView(cancel);
	        	l3.removeView(find);
	        	l4.removeView(to);
				
			}
	    };
	    
	    
	    
	    public String[] getDirectionData(String srcPlace, String destPlace) {

		    String urlString = "http://maps.google.com/maps?f=d&hl=en&saddr="
		            + srcPlace.replace(" ", "%20") + "&daddr=" + destPlace.replace(" ", "%20")
		            + "&ie=UTF8&0&om=0&output=kml";
		    Document doc = null;
		    HttpURLConnection urlConnection = null;
		    URL url = null;
		    String pathConent = "";
		    Boolean b=false;
		    String a[]=null;
		    try {

		        url = new URL(urlString.toString());
		        urlConnection = (HttpURLConnection) url.openConnection();
		        urlConnection.setRequestMethod("GET");
		        urlConnection.setDoOutput(true);
		        urlConnection.setDoInput(true);
		        urlConnection.connect();
		        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		        DocumentBuilder db = dbf.newDocumentBuilder();
		        if(urlConnection.getInputStream().read()>-1){
		        	 doc = db.parse(urlConnection.getInputStream());
		        	 b=true;
		        }
		       

		    } catch (Exception e) {
		    }
		    if(b){
		    	NodeList nl = doc.getElementsByTagName("LineString");
			    for (int s = 0; s < nl.getLength(); s++) {
			        Node rootNode = nl.item(s);
			        NodeList configItems = rootNode.getChildNodes();
			        for (int x = 0; x < configItems.getLength(); x++) {
			            Node lineStringNode = configItems.item(x);
			            NodeList path = lineStringNode.getChildNodes();
			            pathConent = path.item(0).getNodeValue();
			        }
			    }
			    String[] tempContent = pathConent.split(" ");
			    
			    String salida = "";
			    NodeList nl2 = doc.getElementsByTagName("description");
			    for (int s = 0; s < nl2.getLength(); s++) {
			    	Node firstPersonNode = nl2.item(s);
			    	salida += firstPersonNode.getChildNodes().item(0).getNodeValue();
			    }
			    if(salida.indexOf("Distance")>13 && salida.indexOf("(")>-1){
			    	estimacion = salida.substring(salida.indexOf("Distance")+9,salida.indexOf("Distance")+14).replace("&", " ");
			    	estimacion +="km - "+ salida.substring(salida.indexOf("(")+1,salida.indexOf(")"));
			    }
			    return tempContent;
		    }else{
		    	return a;
			    }
			    
		    	
		    
		}

	    
	    private OnClickListener saveButton = new OnClickListener(){
			public void onClick(View arg0) {
				//mbd.deleteAll();
				MapView mapView  = (MapView) findViewById(R.id.mapview);
				LinearLayout l = (LinearLayout) findViewById(R.id.bookmarkControlMapa);
				BookmarksItemMap b = new BookmarksItemMap();
				b.lat = mapView.getMapCenter().toString().split(",")[0];
				b.lon = mapView.getMapCenter().toString().split(",")[1];
				b.name		= inpuBook.getText().toString();			
				mbd.insert(b);
				Toast.makeText(getBaseContext(),"Position saved", Toast.LENGTH_LONG).show();
				l.removeView(cancelBook);
				l.removeView(inpuBook);
				l.removeView(saveBook);
				
			}
	    };
	    
	    private OnTouchListener eventoMapa = new OnTouchListener() {
			public boolean onTouch(View v, MotionEvent event) {
				return false;
			}
		}; 	
	    
	    @Override
		protected boolean isRouteDisplayed() {
			return false;
		}
	    
	    class Marker extends com.google.android.maps.Overlay
	    {
	        GeoPoint location = null;

	        public Marker(GeoPoint location)
	        {
	            super();
	            this.location = location;
	        }

	        @Override
	        public void draw(Canvas canvas, MapView mapView, boolean shadow)
	        {
	            super.draw(canvas, mapView, shadow);
	            Point screenPoint = new Point();
	            mapView.getProjection().toPixels(this.location, screenPoint);
	            canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_menu_home),
	                screenPoint.x, screenPoint.y - 8, null);  // -8 as image is 16px high
	        }
	    }
	   
	    
	}